const FUN = require('../comm/func');
const rCache = require('../model/redis_cache');
const DB = require('../model/model_data');
const dbHelp = require('../comm/db-helper');
const timLib = require('../comm/time-lib');
const dataCalc = require('../comm/data-calc');
const mbLib = require('../comm/modbus-lib');
const PMR = require('../utils/policyManger');

module.exports = class MeterInc
{
  //将数据库选项缓存到redis
  //policy 来自数据库的记录
  //opts 数据库json字段的解析对象
  //CacheCallback 存储执行函数
  static InitCache(policy,opts,CacheCallback)
  {
    let obj=PMR.baseParam(policy);//即将缓存到redis的参数

    //检查json选项
    if( parseInt(policy.record_limit)==0 ||
        parseInt(opts.fetch_period)==0 )
    {
      console.error('wrong meter-inc params',policy.id);
      return false;
    }

    //json options参数存储
    obj.fetch_period = opts.fetch_period;//采样周期
    obj.cache_expire = Number(opts.fetch_period)*2+60;//数据缓存reids有效期
    obj.record_limit = policy.record_limit;//数据库条数上限
    obj.record_duration = 0;//数据库周期上限
    obj.stamp_offset = opts.stamp_offset?Number(opts.stamp_offset)*1000:0;//时间戳偏移值

    obj.data_width=opts.data_width?opts.data_width:'4:f';
    obj.wlist = opts.wlist;//寄存器白名单
    if(opts.out) obj.out = opts.out;//输出变量列表
    if(opts.calc) obj.calc = opts.calc;//输出表达式

    //数据库处理
    dbHelp.createTab(obj.table,policy.uid);
    obj.out_tab=obj.table;//防止dataCalc函数不工作

    //缓存主站参数
    obj.hwid = policy.master;
    obj.role = 'master';
    obj.brother = policy.brother;
    CacheCallback(policy.id,policy.master,obj);//记录到缓存

    //缓存从站参数
    if(Number(policy.brother) && policy.brother!=-1)
    {
      obj.hwid = policy.brother;
      obj.role = 'slave';
      obj.brother = policy.master;
      CacheCallback(policy.id,obj.hwid,obj);//记录到缓存
    }
  }//end InitCache


  //modbus数据总分析
  // topic = {project,devType,func,devId}
  // dConf即InitCache中的obj
  // dataBuf即mq消息内容，buf对象
  static async DataIn(topic, dConf, dataBuf)
  {
    mbLib.mbPacketParse(topic.func, dConf, dataBuf, (last,sConf)=>{
      this.dataHandler(last,sConf,dataBuf,timLib.NowStamp());
    })
  }//end function ModbusTx


  //普通的数据处理,每隔一段时间就求平均值入数据库
  static async dataHandler(last,dConf,data,stamp)
  {
    let nodeDevStamp=PMR.rdNode(dConf,timLib.Rounding(dConf.fetch_period,stamp));
    let nodeDevAddr=nodeDevStamp+':'+last.addr;

    //pcyLog('data in addr',last.addr,data);

    //记地址
    // let obj={};
    // obj[last.addr]=last.addr;
    // rCache.set(nodeDevStamp,'addrs',obj,dConf.cache_expire);

    //记数值
    let newData=[];
    let wlist=dConf.wlist.split(',');//存储白名单
    let data_fmt=dConf.data_width.split(':');//分割数据宽度和数据格式
    for(let i=0;i<last.regNum;i+=(data_fmt[0]/2))
    {
      let reg=Number(last.regStart)+i;
      if(wlist.includes('#'+last.addr) || wlist.includes('#'+last.addr+':'+reg))//只存储白名单
      {
        let regVal=(Number(data[3+i*2])<<8)+Number(data[4+i*2]);

        if(data_fmt[0]==4)//不同字节长度得的处理
          regVal=(regVal<<16)+(Number(data[5+i*2])<<8)+Number(data[6+i*2]);

        if(data_fmt[1]=='f') regVal=FUN.ieee745_toFloat(regVal).toFixed(4);

        let has=await rCache.hasKey(nodeDevAddr,'reg.'+reg);//只存储一次
        if(!has) {
          //pcyLog('push #%d:%d',last.addr,reg,regVal);
          newData.push({reg:reg,value:regVal,name:'#'+last.addr+':'+reg});//加入到数组
        }
      }
    }//end for

    //统一存储
    newData.some((one)=>{
      rCache.push(nodeDevAddr,'reg.'+one.reg,one.value,dConf.cache_expire);//存储到缓存
    })

    //计算增量
    if(newData.length)
    dataCalc.prevDataCalcInc(PMR.rdNode(dConf),dConf,last.addr,(mode,fields,dArray)=>{
      if(dConf.table.includes('dat_json') && mode=='var-json')
        DB.newRcd(dConf.uid,dConf.table,fields,dArray);
        PMR.policyInform('update',dConf);
    })

  }//end funciton

} //end class Modbus